 Cheat Sheets Blog    
Contents

    Syntax
    File Operators
    String Operators
    String Manipulation
    Arrays
    Here Document
    Regular Expressions
    Regexp Matching
    Regexp Match Extraction
    Validate IPs
    Debugging Scripts
    Writing Safer Scripts
    Network Connections
    Simulate Reading From a File
    History
    History Handling
    Adding Timestamps
    Easier History Navigation
    Misc
    Command Completion
    Kill all childs on exit
    Apply ulimit Changes Instantly
    PS1: Escape Non-Print Chars

Bash Cheat Sheet
Syntax
File Operators
The complete list of bash 4.2 test operators:

      -a FILE        True if file exists.
      -b FILE        True if file is block special.
      -c FILE        True if file is character special.
      -d FILE        True if file is a directory.
      -e FILE        True if file exists.
      -f FILE        True if file exists and is a regular file.
      -g FILE        True if file is set-group-id.
      -h FILE        True if file is a symbolic link.
      -L FILE        True if file is a symbolic link.
      -k FILE        True if file has its `sticky' bit set.
      -p FILE        True if file is a named pipe.
      -r FILE        True if file is readable by you.
      -s FILE        True if file exists and is not empty.
      -S FILE        True if file is a socket.
      -t FD          True if FD is opened on a terminal.
      -u FILE        True if the file is set-user-id.
      -w FILE        True if the file is writable by you.
      -x FILE        True if the file is executable by you.
      -O FILE        True if the file is effectively owned by you.
      -G FILE        True if the file is effectively owned by your group.
      -N FILE        True if the file has been modified since it was last read.
    
      FILE1 -nt FILE2  True if file1 is newer than file2 (according to
                       modification date).
    
      FILE1 -ot FILE2  True if file1 is older than file2.
    
      FILE1 -ef FILE2  True if file1 is a hard link to file2.

String Operators
The complete list of bash 4.2 string operators:

      -z STRING      True if string is empty.
    
      -n STRING
         STRING      True if string is not empty.
    
      STRING1 = STRING2
                     True if the strings are equal.
      STRING1 != STRING2
                     True if the strings are not equal.
      STRING1 < STRING2
                     True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
                     True if STRING1 sorts after STRING2 lexicographically.

String Manipulation

${str:position}			# substring starting at position
${str:position:len}		# substring starting at position with length len
${str#ubstring}			# delete shortest match from front
${str##substring}		# delete longest match from front
${str%substring}		# delete shortest match from back
${str%%substring}		# delete longest match from back
${str/substring/replacement}	# string replace
${str/#substring/replacement}	# string replace at front
${str/%substring/replacement}	# string replace at end
${str//substring/replacement}	# global string replace

Arrays
Bash has limited support for associative arrays. Note that indexes must be numbers!

# Declaring associative arrays (since Bash v4)
declare -A arr

# Initializing arrays
arr=("string 1", "string 2", "string 3")
arr=([1]="string 1", [2]="string 2", [3]="string 3")

# Assigning values for indexed arrays
arr[4]="string 4"

# Assigning values for associative arrays
arr["my key"]="my value"

# Accessing the array
${arr[@]}         # Returns all indizes and their items (doesn't work with associative arrays)
${arr[*]}         # Returns all items
${!arr[*]}        # Returns all indizes
${#arr[*]}        # Number elements
${#arr[$n]}       # Length of $nth item

# Pushing to array
arr+=("new string value", "another new value")

Here Document
Bash allow here documents like this

cat <<EOT
[...]
EOT

To disable substitution in the here doc text quote the marker with single or double quotes.

cat <<'EOT'

To strip leading tabs use

cat <<-EOT

Regular Expressions
Regexp Matching
Use conditions with doubled [] and the =~ operator. Ensure not to quote the regular expression. Only BRE are allowed. If the regexp has whitespaces put it in a variable first.

if [[ "$string" =~ ^[0-9]+$ ]]; then 
    echo "Is a number"
fi

Regexp Match Extraction
Variant #1: You can do this with grouping in bash. Despite only BRE being supported grouping works also. Note how you need to set the regexp into a variable because you must not quote it in the if condition!

REGEXP="2013:06:23 ([0-9]+):([0-9]+)"
if [[ "$string" =~ $REGEXP ]]; then
    echo "Hour ${BASH_REMATCH[1]} Minute ${BASH_REMATCH[2]}"
fi

Variant #2: Actually using "expr" can much simpler especially when only on value is to be extracted:

hour=$(expr match "$string" '2013:06:23 \([0-9]\+\)')

Validate IPs
If you need to validate an IP try the following function

function validate_ip {
        local net=$1
        [[ $net =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]] || return 1
        [[ ${net#*/} -le 32 ]] || return 1
        local ip=${net%/*}
        local -a oc=(${ip//\./ })
        [[ ${oc[0]} -le 255 && ${oc[1]} -le 255 && ${oc[2]} -le 255 && ${oc[3]} -le 255 ]] || return 1
        return 0
}

Debugging Scripts
For simple tracing add a

set -x

in the script or append the "-x" to the shebang or run the script like this

bash -x <script name>

As "set -x" enables tracing you can disable it with "set +x" again. This allows tracing only a part of the code (e.g. a condition in an inner loop). Additionally to "-x" you may want to set "-v" to see the shell commands that are executed. Combine both to

set -xv

Writing Safer Scripts
Using

set -e

in a script you ensure that you never forget to check an exit code. Because if you do and the command calls returns an exit code != 0 the script just terminates. Of course you can also use it to not write checks if it is ok to just bail out.
Network Connections

# Establish a connection to 91.92.93.94:80 on file handle 4 with
if ! exec 4<> /dev/tcp/91.92.93.94/80; then
	echo "ERROR: Connection failed!"
fi

# Write something
echo -e "GET / HTTP/1.0\n" >&4

# Read something
cat <&4

# Close the socket
exec <&4-
exec >&4-

Simulate Reading From a File
Sometimes you might need to pass a file name when you want to pipe output from a commands. Then you could write to a file first and then used it, but you can also use the ">()" or "<()" operator. This can be used with all tools that demand a file name paramter:

diff <(echo abc;echo def) <(echo abc;echo abc)

History
History Handling
Here are some improvements for the bash history handling:

unset HISTFILE      # Stop logging history in this bash instance
HISTIGNORE="[ ]*"   # Do not log commands with leading spaces
HISTIGNORE="&"      # Do not log a command multiple times

# Change up/down arrow key behaviour to navigate only similar commands
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

Adding Timestamps
To add timestamps to your history set the following environment variable:

HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " # Log with timestamps

Easier History Navigation
If you do not like Ctrl-R to nagivate the history you can define other keys as PgUp and PgDown in /etc/inputrc:

   "\e[5~": history-search-backward
   "\e[6~": history-search-forward

Misc
Command Completion
How to setup your own bash completion schemas. Here is a git example:

complete -W 'add branch checkout clone commit diff grep init log merge mv pull push rebase rm show status tag' git

complete -p    # To list defined completion schemes

Note that the above example propably already comes prepared with your Linux distribution. You might want to check default definitions installed in /etc/bash_completion.d for a good starting point.
Kill all childs on exit

trap true TERM
kill -- -$$

Apply ulimit Changes Instantly
The problem behind this is documented in this blog post but it boils down to try to use the "-i" switch:

sudo -i -u <user>

If it doesn't work you might need to investigate and change the PAM configuration.
PS1: Escape Non-Print Chars
To avoid incorrect line break behaviour when editing the command line you need to escape control characters in PS1 like this:

\[color definition\]

For example:

\[\033[31m\] some text \[\033[0m\]

	

